package com.zboot.comm.es.util;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.apache.lucene.util.CollectionUtil;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.util.StringUtils;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import java.util.function.Predicate;

/**
 * SLOGAN:让现在编程未来
 *
 * @author <a href="mailto:linfeng@dtstack.com">林丰</a> 2019/8/5.
 * @description es条件入参封装
 */
@Getter
@Setter
@NoArgsConstructor
public class ElasticSearchWrapper implements java.io.Serializable {
    private static final long serialVersionUID = -3406397554541655240L;

    private SearchSourceBuilder searchSourceBuilder; // es最终调用栈
    private BoolQueryBuilder boolQueryBuilder;      // es_bool_query

    private HighlightBuilder highlightBuilder;

    private volatile PredicateEnum predicateEnum = PredicateEnum.MUST; // 谓语: 默认为must

    public static final String wildCardSplice = "*{}*";       // es-分词匹配拼接
    public static final String KeywordSplice = "{}.keyword"; // es-keyword拼接
    public static final String ASC = "ASC";

    public ElasticSearchWrapper(SearchSourceBuilder searchSourceBuilder, BoolQueryBuilder boolQueryBuilder) {
        this.searchSourceBuilder = searchSourceBuilder;
        this.boolQueryBuilder = boolQueryBuilder;
    }

    /**
     * 谓语判断
     * 主要做谓语和宾语的分离:
     * <p>谓语:must、mustNot、should</p>
     * <p>宾语:term、terms、range、wildCard、fuzzy...(未完待续)</p>
     * <p>用法:
     * ElasticSearchWrapper
     * .createBool()
     * .mustTermIfNonNull("user_id", "111")
     * .mustTermIfNonBlank("user_name", "张三")
     * .should().rangeIfNonNull("integral", 200, 300)                                               // 等价于 shouldRangeIfNonNull()
     * .should().terms(Collections::nonEmpty, "tag_id", ImmutableList.of("1001", "1002", "1003"))   // 等价于 shouldTerms()
     *
     * </p>
     *
     * @param queryBuilder queryBuilder
     */
    private void judgePredicate(QueryBuilder queryBuilder) {
        if (PredicateEnum.MUST.equals(predicateEnum)) {
            boolQueryBuilder.must(queryBuilder);
        } else if (PredicateEnum.SHOULD.equals(predicateEnum)) {
            boolQueryBuilder.should(queryBuilder);
        } else if (PredicateEnum.MUST_NOT.equals(predicateEnum)) {
            boolQueryBuilder.mustNot(queryBuilder);
        }
    }

    /**
     * 目前只提供bool query方式，es布尔查询符合绝大部分查询场景。
     *
     * @return
     */
    public static ElasticSearchWrapper createBool() {
        return new ElasticSearchWrapper(new SearchSourceBuilder(), QueryBuilders.boolQuery());
    }

    /**
     * 这里方法取名为get()，后续可能会有增删改，则取名getQuery()便于区分，目前来看查询相对较多，其它增删改基本为指定id。
     *
     * @return
     */
    public SearchSourceBuilder get() {
        if(this.highlightBuilder!=null) {
            this.getSearchSourceBuilder().highlighter(this.highlightBuilder);
        }
        return this.getSearchSourceBuilder().query(this.getBoolQueryBuilder());
    }

    /**
     * 嵌套BoolQuery -> must
     *
     * @param func 嵌套BoolQuery函数表达式
     * @return
     */
    public ElasticSearchWrapper must(Function<ElasticSearchWrapper, ElasticSearchWrapper> func) {
        return must(true, func);
    }

    /**
     * 嵌套BoolQuery -> must
     *
     * @param expression 执行先决条件 true才执行
     * @param func       嵌套BoolQuery函数表达式
     * @return
     */
    public ElasticSearchWrapper must(boolean expression, Function<ElasticSearchWrapper, ElasticSearchWrapper> func) {
        if (expression) {
            ElasticSearchWrapper wrapper = func.apply(createBool());
            this.getBoolQueryBuilder().must(wrapper.getBoolQueryBuilder());
        }
        return this;
    }

    /**
     * 嵌套BoolQuery -> should
     *
     * @param func 嵌套BoolQuery函数表达式
     * @return
     */
    public ElasticSearchWrapper should(Function<ElasticSearchWrapper, ElasticSearchWrapper> func) {
        return should(true, func);
    }

    /**
     * 嵌套BoolQuery -> should
     *
     * @param expression 执行先决条件 true才执行
     * @param func       嵌套BoolQuery函数表达式
     * @return
     */
    public ElasticSearchWrapper should(boolean expression, Function<ElasticSearchWrapper, ElasticSearchWrapper> func) {
        if (expression) {
            ElasticSearchWrapper wrapper = func.apply(createBool());
            this.getBoolQueryBuilder().should(wrapper.getBoolQueryBuilder());
        }
        return this;
    }

    public ElasticSearchWrapper must() {
        setPredicateEnum(PredicateEnum.MUST);
        return this;
    }

    public ElasticSearchWrapper mustNot() {
        setPredicateEnum(PredicateEnum.MUST_NOT);
        return this;
    }

    public ElasticSearchWrapper should() {
        setPredicateEnum(PredicateEnum.SHOULD);
        return this;
    }

    /**
     * 根据PredicateEnum判断谓语动词，term查询
     *
     * @param predicate 先决条件
     * @param name      字段名
     * @param val       值
     * @return
     */
    public ElasticSearchWrapper term(Predicate<Object> predicate, String name, Object val) {
        if (predicate.test(val)) {
            TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery(name, val);
            judgePredicate(termQueryBuilder);
        }
        return this;
    }

    /**
     * 字段精确匹配（nonNull）
     *
     * @param name
     * @param val
     * @return
     */
    public ElasticSearchWrapper termIfNonNull(String name, Object val) {
        if (Objects.nonNull(val)) {
            TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery(name, val);
            judgePredicate(termQueryBuilder);
        }
        return this;
    }

    /**
     * 字段多values匹配，该字段为数组。 类似于sql: in(1,3,4) -> must
     *
     * @param name   字段名
     * @param values 值集合
     * @return ElasticSearchWrapper
     */
    public ElasticSearchWrapper mustTermsIfNonEmptyVal(String name, List<Integer> values) {
        if (values!=null && values.size()>0) {
            boolQueryBuilder.must(QueryBuilders.termsQuery(name, values));
        }
        return this;
    }

    /**
     * 字段精确匹配（nonEmpty）
     *
     * @param name
     * @param val
     * @return
     */
    public ElasticSearchWrapper termIfNonEmpty(String name, String val) {
        if (val!=null && val.length()>0 && name!=null) {
            TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery(name, val);
            judgePredicate(termQueryBuilder);
        }
        return this;
    }

    public ElasticSearchWrapper mustTerm(String name, Object val) {
//        Objects.requireNonNull(name);
//        Objects.requireNonNull(val);
        boolQueryBuilder.must(QueryBuilders.termQuery(name, val));
        return this;
    }

    public ElasticSearchWrapper mustTerm(Predicate<Object> predicate, String name, Object val) {
        if (predicate.test(val)) {
            boolQueryBuilder.must(QueryBuilders.termQuery(name, val));
        }
        return this;
    }

    /**
     * 字段精确匹配（nonNull）-> must
     *
     * @param name
     * @param val
     * @return
     */
    public ElasticSearchWrapper mustTermIfNonNull(String name, Object val) {
        if (Objects.nonNull(val)) {
            boolQueryBuilder.must(QueryBuilders.termQuery(name, val));
        }
        return this;
    }

    /**
     * 字段精确匹配（nonEmpty）-> must
     *
     * @param name
     * @param val
     * @return
     */
    public ElasticSearchWrapper mustTermIfNonEmpty(String name, String val) {
        if (val!=null && val.length()>0 && name!=null) {
            boolQueryBuilder.must(QueryBuilders.termQuery(name, val));
        }
        return this;
    }

    /**
     * 字段精确匹配（nonBlank）-> must
     *
     * @param name
     * @param val
     * @return
     */
    public ElasticSearchWrapper mustTermIfNonBlank(String name, String val) {
        if (val!=null && val.length()>0 && name!=null) {
            boolQueryBuilder.must(QueryBuilders.termQuery(name, val));
        }
        return this;
    }

    /**
     * 字段精确匹配（nonBlank）-> must,keyword
     *
     * @param name
     * @param val
     * @return
     */
    public ElasticSearchWrapper mustTermIfNonBlankKeyWord(String name, String val) {
        if (val!=null && val.length()>0 && name!=null) {
            boolQueryBuilder.must(QueryBuilders.termQuery(String.format(KeywordSplice, name), val));
        }
        return this;
    }

    /**
     * 字段多values匹配，该字段为数组。 类似于sql: in(1,3,4) -> must,keyword
     *
     * @param name   字段名
     * @param values 值集合
     * @return ElasticSearchWrapper
     */
    public ElasticSearchWrapper mustTermsIfNonEmptyKeyWord(String name, List<String> values) {
        if (values!=null && values.size()>0) {
            boolQueryBuilder.must(QueryBuilders.termsQuery(String.format(KeywordSplice, name), values));
        }
        return this;
    }

    /**
     * 字段精确匹配 -> should
     *
     * @param name
     * @param val
     * @return
     */
    public ElasticSearchWrapper shouldTerm(String name, Object val) {
//        Objects.requireNonNull(name);
//        Objects.requireNonNull(val);
        boolQueryBuilder.should(QueryBuilders.termQuery(name, val));
        return this;
    }

    /**
     * 字段精确匹配 -> should
     *
     * @param predicate
     * @param name
     * @param val
     * @return
     */
    public ElasticSearchWrapper shouldTerm(Predicate<Object> predicate, String name, Object val) {
        if (predicate.test(val)) {
            boolQueryBuilder.should(QueryBuilders.termQuery(name, val));
        }
        return this;
    }

    /**
     * 字段精确匹配（nonNull）-> should
     *
     * @param name
     * @param val
     * @return
     */
    public ElasticSearchWrapper shouldTermIfNonNull(String name, Object val) {
        if (Objects.nonNull(val)) {
            boolQueryBuilder.should(QueryBuilders.termQuery(name, val));
        }
        return this;
    }

    /**
     * 字段精确匹配（nonEmpty）-> should
     *
     * @param name
     * @param val
     * @return
     */
    public ElasticSearchWrapper shouldTermIfNonEmpty(String name, String val) {
        if (val!=null && val.length()>0 && name!=null) {
            boolQueryBuilder.should(QueryBuilders.termQuery(name, val));
        }
        return this;
    }

    /**
     * 字段精确匹配（nonBlank）-> should
     *
     * @param name
     * @param val
     * @return
     */
    public ElasticSearchWrapper shouldTermIfNonBlank(String name, String val) {
        if (val!=null && val.length()>0 && name!=null) {
            boolQueryBuilder.should(QueryBuilders.termQuery(name, val));
        }
        return this;
    }

    /**
     * 字段多values匹配，该字段为数组。 类似于sql: in(1,3,4) -> should
     *
     * @param name
     * @param values
     * @return
     */
    public ElasticSearchWrapper shouldTermsIfNonEmpty(String name, Collection<?> values) {
        if (values!=null && values.size()>0) {
            boolQueryBuilder.should(QueryBuilders.termsQuery(name, values));
        }
        return this;
    }

    /**
     * 根据PredicateEnum判断谓语动词，term查询
     *
     * @param predicate 先决条件
     * @param name      字段名
     * @param values    值集合
     * @return
     */
    public ElasticSearchWrapper terms(Predicate<Collection<?>> predicate, String name, Collection<?> values) {
        if (predicate.test(values)) {
            TermsQueryBuilder termsQueryBuilder = QueryBuilders.termsQuery(name, values);
            judgePredicate(termsQueryBuilder);
        }
        return this;
    }

    public ElasticSearchWrapper terms(String name, Collection<?> values) {
        TermsQueryBuilder termsQueryBuilder = QueryBuilders.termsQuery(name, values);
        judgePredicate(termsQueryBuilder);
        return this;
    }

    /**
     * 字段多values匹配，该字段为数组。 类似于sql: in(1,3,4) -> must
     *
     * @param name
     * @param values
     * @return
     */
    public ElasticSearchWrapper mustTerms(String name, Collection<?> values) {
        boolQueryBuilder.must(QueryBuilders.termsQuery(name, values));
        return this;
    }

    /**
     * 字段多values匹配，该字段为数组。 类似于sql: in(1,3,4) -> must
     *
     * @param name
     * @param values
     * @return
     */
    public ElasticSearchWrapper mustTermsIfNonEmpty(String name, Collection<?> values) {
        if (values!=null && values.size()>0) {
            boolQueryBuilder.must(QueryBuilders.termsQuery(name, values));
        }
        return this;
    }

    /**
     * 范围查询
     *
     * @param expression true则执行该过滤条件 false不执行
     * @param name       字段名
     * @param from       起始值
     * @param to         终止值
     * @return ElasticSearchWrapper
     */
    public ElasticSearchWrapper range(boolean expression, String name, Object from, Object to) {
        if (expression) {
            RangeQueryBuilder rangeQueryBuilder = QueryBuilders
                    .rangeQuery(name)
                    .from(from)
                    .to(to);
            judgePredicate(rangeQueryBuilder);
        }
        return this;
    }

    public ElasticSearchWrapper rangeIfNonNull(String name, Object from, Object to) {
        if (Objects.nonNull(from) || Objects.nonNull(to)) {
            RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery(name);
            if (Objects.nonNull(from)) {
                rangeQueryBuilder.from(from);
            }
            if (Objects.nonNull(to)) {
                rangeQueryBuilder.to(to);
            }
            judgePredicate(rangeQueryBuilder);
        }
        return this;
    }


    /**
     * 范围查询-> must
     *
     * @param expression true则执行该过滤条件 false不执行
     * @param name       字段名
     * @param from       起始值
     * @param to         终止值
     * @return ElasticSearchWrapper
     */
    public ElasticSearchWrapper mustRange(boolean expression, String name, Object from, Object to) {
        if (expression) {
            RangeQueryBuilder rangeQueryBuilder = QueryBuilders
                    .rangeQuery(name)
                    .from(from)
                    .to(to);
            boolQueryBuilder.must(rangeQueryBuilder);
        }
        return this;
    }

    /**
     * 范围查询-> should
     *
     * @param expression true则执行该过滤条件 false不执行
     * @param name       字段名
     * @param from       起始值
     * @param to         终止值
     * @return ElasticSearchWrapper
     */
    public ElasticSearchWrapper shouldRange(boolean expression, String name, Object from, Object to) {
        if (expression) {
            RangeQueryBuilder rangeQueryBuilder = QueryBuilders
                    .rangeQuery(name)
                    .from(from)
                    .to(to);
            boolQueryBuilder.should(rangeQueryBuilder);
        }
        return this;
    }

    /**
     * 范围查询-> must、from和to分开判断，不为空则加入过滤
     *
     * @param name 字段名
     * @param from 起始值
     * @param to   终止值
     * @return
     */
    public ElasticSearchWrapper mustRangeIfNonNull(String name, Object from, Object to) {
        if (Objects.nonNull(from) || Objects.nonNull(to)) {
            RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery(name);
            if (Objects.nonNull(from)) {
                rangeQueryBuilder.from(from);
            }
            if (Objects.nonNull(to)) {
                rangeQueryBuilder.to(to);
            }
            boolQueryBuilder.must(rangeQueryBuilder);
        }
        return this;
    }

    /**
     * 范围查询 功能上同
     *
     * @param mapper T转换为M的映射
     * @param <T>    from和to的对象类型
     * @param <M>    es执行查询的对象类型
     */
    public <T, M> ElasticSearchWrapper mustRangeIfNonNull(String name, T from, T to, Function<T, M> mapper) {
        if (Objects.nonNull(from) || Objects.nonNull(to)) {
            RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery(name);
            if (Objects.nonNull(from)) {
                rangeQueryBuilder.from(mapper.apply(from));
            }
            if (Objects.nonNull(to)) {
                rangeQueryBuilder.to(mapper.apply(to));
            }
            boolQueryBuilder.must(rangeQueryBuilder);
        }
        return this;
    }

    /**
     * es-分词搜索 多字段
     *
     * @param search 搜索输入
     * @param names  字段列举
     */
    public ElasticSearchWrapper wildcardIfNonBlank(String search, String... names) {
        if (search!=null && search.length()>0 && names!=null) {
            String wildSearch = String.format(ElasticSearchWrapper.wildCardSplice, search);
            for (String name : names) {
                WildcardQueryBuilder wildcardQueryBuilder = QueryBuilders.wildcardQuery(name, wildSearch);
                judgePredicate(wildcardQueryBuilder);
            }
        }
        return this;
    }

    /**
     * es-搜索.keyword 多字段
     *
     * @param search 搜索输入
     * @param names  字段列举
     */
    public ElasticSearchWrapper wildcardWithKeyword(String search, String... names) {
        if (search!=null && search.length()>0 && names!=null) {
            String wildSearch = String.format(ElasticSearchWrapper.wildCardSplice, search);
            for (String name : names) {
                WildcardQueryBuilder wildcardQueryBuilder = QueryBuilders.wildcardQuery(String.format(KeywordSplice, name), wildSearch);
                judgePredicate(wildcardQueryBuilder);
            }
        }
        return this;
    }

    /**
     * es-搜索.keyword 多字段
     *
     * @param search 搜索输入
     * @param names  字段列举
     */
    public ElasticSearchWrapper mustWildcardWithKeyword(String search, String... names) {
        if (search!=null && search.length()>0 && names!=null) {
            String wildSearch = String.format(ElasticSearchWrapper.wildCardSplice, search);
            for (String name : names) {
                WildcardQueryBuilder wildcardQueryBuilder = QueryBuilders.wildcardQuery(String.format(KeywordSplice, name), wildSearch);
                boolQueryBuilder.must(wildcardQueryBuilder);
            }
        }
        return this;
    }



    /**
     * es-分词搜索 多字段
     *
     * @param search    搜索输入
     * @param name      字段
     * @param isKeyword 是否为text关键字搜索
     */
    public ElasticSearchWrapper wildcardIfNonBlank(boolean isKeyword, String name, String search) {
        if (search!=null && search.length()>0 && name!=null) {
            String wildSearch = String.format(wildCardSplice, search);
            WildcardQueryBuilder wildcardQueryBuilder = QueryBuilders.wildcardQuery(isKeyword ? String.format(KeywordSplice, name) : name, wildSearch);
            judgePredicate(wildcardQueryBuilder);
        }
        return this;
    }

    /**
     * es-match搜索
     *
     * @param search 搜索输入
     * @param name   字段
     */
    public ElasticSearchWrapper matchIfNonBlank(String name, String search) {
        if (search!=null && search.length()>0 && name!=null) {
            MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery(name, search);
            judgePredicate(matchQueryBuilder);
        }
        return this;
    }

    /**
     * fuzzy查询
     *
     * @param name   字段
     * @param search 搜索输入
     */
    public ElasticSearchWrapper fuzzyIfNonBlank(String name, String search) {
        if (search!=null && search.length()>0 && name!=null) {
            FuzzyQueryBuilder fuzzyQueryBuilder = QueryBuilders.fuzzyQuery(name, search).fuzziness(Fuzziness.AUTO); // 自动
            judgePredicate(fuzzyQueryBuilder);
        }
        return this;
    }

    /**
     * 排序
     *
     * @param name  排序字段
     * @param order 排序规则 ASC DESC
     */
    public ElasticSearchWrapper sort(String name, SortOrder order) {
//            Objects.requireNonNull(name);
//            Objects.requireNonNull(order);
        getSearchSourceBuilder().sort(name, order);
        return this;
    }

    public ElasticSearchWrapper sortIfNonEmpty(String name, SortOrder order) {
        if (name!=null && name.length()>0) {
            getSearchSourceBuilder().sort(name, order);
        }
        return this;
    }

    /**
     * 默认为DESC降序
     *
     * @param name        排序字段
     * @param defaultName 当排序字段为空或empty时的默认排序字段
     * @param order       升序ASC 降序DESC ,order为空时默认desc
     */
    public ElasticSearchWrapper sortDefault(String name, String defaultName, String order) {
        Objects.requireNonNull(defaultName);
        getSearchSourceBuilder()
                .sort(StringUtils.isEmpty(name) ? defaultName : name,
                        ASC.equalsIgnoreCase(order) ? SortOrder.ASC : SortOrder.DESC
                );
        return this;
    }

    /**
     * 分页参数(导出)
     *
     * @param from 起始偏移量
     * @param size pageSize
     */
    public ElasticSearchWrapper fromSize(boolean export, int maxExport, int from, int size) {
        if (export) {
            getSearchSourceBuilder().from(0).size(maxExport);
        } else {
            getSearchSourceBuilder().from(from).size(size);
        }
        return this;
    }



    /**
     * 分页参数(导出)动态参数
     *
     * @param maxExport 最大导出量
     */
    public ElasticSearchWrapper fromSizeDynamic(int maxExport, Integer t) {
        if (t != null) {
            getSearchSourceBuilder().from((t - 1) * maxExport).size(maxExport);
        } else {
            return this;
        }
        return this;
    }

    /**
     * 分页参数
     *
     * @param from 起始偏移量
     * @param size pageSize
     */
    public ElasticSearchWrapper fromSize(int from, int size) {
        getSearchSourceBuilder().from(from).size(size);
        return this;
    }

    public ElasticSearchWrapper from(int from) {
        getSearchSourceBuilder().from(from);
        return this;
    }

    public ElasticSearchWrapper size(int size) {
        getSearchSourceBuilder().size(size);
        return this;
    }

    /**
     * 取得字段
     *
     * @param includes 包含
     * @param excludes 不包含
     */
    public ElasticSearchWrapper fetchSource(String[] includes, String[] excludes) {
        getSearchSourceBuilder().fetchSource(includes, excludes);
        return this;
    }

    public ElasticSearchWrapper includes(String[] includes) {
        getSearchSourceBuilder().fetchSource(includes, null);
        return this;
    }

    public ElasticSearchWrapper excludes(String[] excludes) {
        getSearchSourceBuilder().fetchSource(null, excludes);
        return this;
    }

    public ElasticSearchWrapper highlight(String... fields) {
        if(fields!=null && fields.length>0) {
            for (String field : fields) {
                getHighlightBuilder().field(field);
            }
        }
        return this;
    }

    public HighlightBuilder getHighlightBuilder() {
        if(this.highlightBuilder==null) {
            this.highlightBuilder = new HighlightBuilder();
            this.highlightBuilder.requireFieldMatch(false);
            this.highlightBuilder.preTags("<span style='color:#F56C6C'>");
            this.highlightBuilder.postTags("</span>");
        }
        return this.highlightBuilder;
    }

    public static void main(String[] args) {
        /**
         * demo示例
         */
        SearchSourceBuilder searchSourceBuilder = ElasticSearchWrapper
                .createBool()
                .mustTermIfNonNull("user_id", "111")
                .mustTermIfNonBlank("user_name", "张三")
                .mustNot().term(Objects::nonNull, "user_id", "000")
                .should().rangeIfNonNull("integral", 200, 300)
                .shouldTerm("tag_id", Arrays.asList("1001", "1002", "1003"))
                //.should().terms(CollectionUtil::isNotEmpty, ) // 等价于 shouldTerms()
                .must(true,
                        x -> x
                                .should().term(p -> true, "user_id", "888")
                                .should().terms(p -> true, "tag_id", Arrays.asList("8001", "8002"))
                )
                .should(true,
                        x -> x // 嵌套bool
                                .must().fuzzyIfNonBlank("user_name", "fuzzy_search")
                                .mustRange(true, "score", 70, 80)
                                .should().wildcardIfNonBlank("哈", "user_name", "user_phone")
                                .should().wildcardIfNonBlank(true, "user_address", "和")
                                .should(true,
                                        y -> y // 嵌套bool
                                                .mustNot().termIfNonEmpty("type", "B")
                                                .must().termIfNonNull("phone", "13330244367")
                                )
                )
                .fromSize(100, 10)
                .get();

        System.out.println(searchSourceBuilder.toString());

    }
}
